import paramiko
import paramiko.auth_strategy
import tarfile
import os
import shutil  # 用于删除本地目录
import logging
import stat  # 用于检查文件的权限
from PyQt6.QtWidgets import QApplication, QDialog, QFileDialog
from PyQt6.QtCore import QThread, pyqtSignal  # 导入 QThread 和信号
from SocUpdate.soc_update import Ui_Dialog


class AuthStrategy(paramiko.auth_strategy.AuthStrategy):
    def __init__(self, ssh_config, username):
        super().__init__(ssh_config)
        self.username = username

    def get_sources(self):
        yield paramiko.auth_strategy.NoneAuth(self.username)


class WorkerThread(QThread):
    output_signal = pyqtSignal(str)  # 定义信号以发送输出

    def __init__(self, extract_path):
        super(WorkerThread, self).__init__()
        self.extract_path = extract_path

    def run(self):
        self.runInstallScript(self.extract_path)

    def runInstallScript(self, extract_path):
        logging.debug(f"Running install script with extract path: {extract_path}")

        # SSH连接信息
        target_ip = '192.168.2.11'
        username = 'root'
        j3_app_dir = '/app/chery'
        j3_deploy_dir = os.path.join(extract_path, 'j3_deploy')  # 解压后 j3_deploy 的路径

        # 设置 SSH 连接
        ssh_config = paramiko.SSHConfig()
        auth_strategy = AuthStrategy(ssh_config, username)
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        try:
            self.output_signal.emit(f'尝试连接到 {target_ip}...')
            ssh.connect(target_ip, username=username, auth_strategy=auth_strategy)
            self.output_signal.emit(f'成功连接到 {target_ip}.')

            # 1. remount rw /app
            self.execute_command(ssh, "mount -o remount rw /app")

            # 2. 删除旧的 j3_app_dir
            self.execute_command(ssh, f"rm -rf {j3_app_dir}")

            # 3. 创建新的 j3_app_dir
            self.execute_command(ssh, f"mkdir -p {j3_app_dir}")

            # 4. 通过 SCP 传输 j3_deploy 目录下的文件和文件夹
            self.upload_files(ssh, j3_deploy_dir, j3_app_dir)

            # 5. 删除解压目录（本地执行）
            shutil.rmtree(extract_path)  # 删除本地解压目录
            self.output_signal.emit(f'删除本地解压目录: {extract_path}')

            # 6. 重启设备
            self.execute_command(ssh, "/sbin/reboot")

            self.output_signal.emit('脚本执行完成')
        except Exception as e:
            self.output_signal.emit(f'脚本执行错误: {str(e)}')
            logging.error(f"Script execution error: {str(e)}")
        finally:
            ssh.close()

    def execute_command(self, ssh, command):
        logging.debug(f"Executing command: {command}")
        stdin, stdout, stderr = ssh.exec_command(command)

        stdout_lines = stdout.read().decode('utf-8').strip()
        stderr_lines = stderr.read().decode('utf-8').strip()

        if stdout_lines:
            self.output_signal.emit(f"标准输出: {stdout_lines}")
            logging.debug(f"Command output: {stdout_lines}")
        if stderr_lines:
            self.output_signal.emit(f"错误: {stderr_lines}")
            logging.error(f"Command error: {stderr_lines}")

    import stat  # 用于检查文件的权限

    def upload_files(self, ssh, local_path, remote_path):
        sftp = ssh.open_sftp()
        try:
            # 遍历 j3_deploy 目录下的所有文件和子目录
            for dirpath, dirnames, filenames in os.walk(local_path):
                remote_dir = os.path.join(remote_path, os.path.relpath(dirpath, local_path))

                # 创建远程目录
                try:
                    sftp.mkdir(remote_dir)
                    self.output_signal.emit(f'创建远程目录: {remote_dir}')
                except IOError:
                    self.output_signal.emit(f'远程目录已经存在: {remote_dir}')

                for filename in filenames:
                    local_file = os.path.join(dirpath, filename)
                    remote_file = os.path.join(remote_dir, filename)
                    try:
                        self.output_signal.emit(f'准备上传文件: {local_file} 到 {remote_file}')
                        sftp.put(local_file, remote_file)
                        self.output_signal.emit(f'成功上传文件: {local_file} 到 {remote_file}')

                        # 检查本地文件权限，若有可执行权限则远程文件也需要赋予执行权限
                        mode = os.stat(local_file).st_mode
                        if mode & stat.S_IXUSR:  # 如果本地文件是可执行文件
                            self.output_signal.emit(f'为远程文件设置可执行权限: {remote_file}')
                            self.execute_command(ssh, f'chmod +x {remote_file}')
                    except Exception as e:
                        self.output_signal.emit(f'文件上传失败: {local_file}, 错误: {str(e)}')
                        logging.error(f'Failed to upload file: {local_file}, error: {str(e)}')
        finally:
            sftp.close()

class FileUploader(QDialog):
    def __init__(self):
        super(FileUploader, self).__init__()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)

        self.ui.chooseSocBag.clicked.connect(self.handleButtonClick)

    def handleButtonClick(self):
        self.ui.chooseSocBag.setEnabled(False)
        file_path, _ = QFileDialog.getOpenFileName(self, '选择 tar.gz 文件', '', 'Tar Files (*.tar.gz)')

        if file_path:
            self.ui.textEdit.append(f'选择的文件: {file_path}')
            self.uploadFile(file_path)

        self.ui.chooseSocBag.setEnabled(True)

    def uploadFile(self, file_path):
        logging.basicConfig(level=logging.DEBUG)
        logging.debug("Starting uploadFile method.")

        extract_path = file_path.rstrip('.tar.gz')
        with tarfile.open(file_path, 'r:gz') as tar:
            tar.extractall(path=extract_path)
            self.ui.textEdit.append(f'解压到: {extract_path}')

        # 创建工作线程并连接信号
        self.worker_thread = WorkerThread(extract_path)
        self.worker_thread.output_signal.connect(self.updateTextEdit)
        self.worker_thread.start()

    def updateTextEdit(self, text):
        self.ui.textEdit.append(text)
